package com.example.jddjxx.selenium;

import com.example.jddjxx.ChromeDriver;
import com.example.jddjxx.constant.Msg;
import com.example.jddjxx.constant.Scheme;
import com.example.jddjxx.web.controller.vo.SafeAutoParam;
import com.example.jddjxx.web.entity.Ent;
import com.example.jddjxx.web.entity.H2Ent;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.example.jddjxx.ChromeDriver.destroyInstance;
import static com.example.jddjxx.constant.Scheme.easy;
import static com.example.jddjxx.constant.Scheme.findByKeyword;


/**
 * <p>AutoSubscribe</p>
 * description
 *
 * @author 邓峰峰
 * @date 2020/5/8 17:19
 */
public class AutoOperate {
    private static boolean login;


    /**
     * 打开开放平台网址网址
     */
    public AutoOperate open() {
        try {
            ChromeDriver.getInstance().get("https://opendj.jd.com/index.html");
        } catch (Exception exception) {
            ChromeDriver.getInstance().close();
            ChromeDriver.getInstance().get("https://opendj.jd.com/index.html");
        }
        return this;
    }


    /**
     * 关闭驱动
     */
    @SneakyThrows
    public void close() {
        Thread.sleep(3000);
        destroyInstance();
    }

    /**
     * 刷新
     */
    public void refresh() {
        open();
    }


    /**
     * 登录
     */
    public AutoOperate login(String username, String password) {

        //切换到登陆页
        final WebElement loginHtmlEle = findElementByXPath("/html/body/div[2]/ol/li[1]");
        doClick(loginHtmlEle);

        //点击开发者登陆
        final WebElement devLoginEle = findElementByXPath("/html/body/div[2]/ul/li[1]/div/a[2]");
        doClick(devLoginEle);

        final WebElement userNameEle = findElementById("userName");
        final WebElement passwordEle = findElementById("password");

        final WebElement loginEle = findElementById("longin");
        doSendKeys(userNameEle, username);
        //密码在发布的时候应该在代码中去掉
        doSendKeys(passwordEle, password);
        //获取验证码,等待页面手动输入
        final WebElement validateCodeEle = findElementById("validateCode");
        waitInputAndLogin(loginEle, validateCodeEle);


        return this;
    }


    /**
     * 到已授权应用的页面
     *
     * @return
     */
    public AuthedAppOperate toAuthedApp() {
        WebElement manageCenterEle = getManageCenter();
        //点击管理中心
        doClick(manageCenterEle);

        //点击已授权应用
        final WebElement authedAppEle = findElementByXPath("/html/body/div[2]/ul/li[1]/ul/li[3]/a");
        doClick(authedAppEle);
        AuthedAppOperate operate = new AuthedAppOperate();
        return operate;
    }

    /**
     * 获取管理中心的按钮
     *
     * @return
     */
    @SneakyThrows
    private WebElement getManageCenter() {

        WebElement manageCenterEle = null;
        try {
            Thread.sleep(200);
            manageCenterEle = findElementByXPath("/html/body/div[1]/div/div/div[3]/ul/li[5]/h2/a");
        } catch (Exception e) {
            try {
                Thread.sleep(200);
                manageCenterEle = findElementByXPath("/html/body/div[1]/div/div/div[2]/ul/li[5]/h2/a");
            } catch (Exception exception) {
                Thread.sleep(500);
                return getManageCenter();
            }

        }
        return manageCenterEle;
    }

    /**
     * 管理中心已授权应用操作页面
     */
    public static class AuthedAppOperate {

        /**
         * 获取所有企业
         * @return
         */
        public List<H2Ent> getAllEnt() {
            final WebElement tbodyEle = findElementByXPath("/html/body/div[3]/div/div[2]/form/table/tbody");
            final List<WebElement> trElements = tbodyEle.findElements(By.tagName("tr"));
            // 去掉第一行的表头,获取所有的app 行
            return trElements.stream()
                    .skip(1)
                    .map(EnterpriseTr::new)
                    .map(etr->{
                        final String appName = etr.getAppName().getText();
                        final String venderIdStr = etr.getVenderIdStr();
                        boolean test = false;
                        if(appName.contains("牵牛花")){
                            test = true;
                        }
                        H2Ent h2Ent = new H2Ent();
                        h2Ent.setTest(test);
                        h2Ent.setName(appName);
                        h2Ent.setVendorId(venderIdStr);
                        return h2Ent;
                    })
                    .collect(Collectors.toList());

        }

        /**
         * 接口配置及测试操作页面
         */
        public static class InterfaceConfigAndTestOperate {

            /**
             * 测试操作页面
             */
            public static class TestOperate {
                private Set<Msg> msgs;

                public TestOperate(Set<Msg> msgs) {
                    this.msgs = msgs;
                }

                /**
                 * 从测试页面获取所有的tr
                 *
                 * @return
                 */
                @SneakyThrows
                private List<WebElement> getAllTr() {
                    try {
                        Thread.sleep(300);
                        //获取接口列表div
                        final WebElement interfaceContent = findElementById("test_interface_content");
//                        final List<WebElement> divs = interfaceContent.findElements(By.tagName("div"));
                        return interfaceContent.findElements(By.tagName("tr"));
                    } catch (Exception e) {
                        Thread.sleep(1000);
                        return getAllTr();
                    }
                }

                /**
                 * 从测试页面找到所有的消息订阅的tr
                 *
                 * @return
                 */
                private List<TestMsgTr> findAllTestMsgTr() {
//                    final Map<String, Msg> map = Msg.map();
                    final List<WebElement> allTr = getAllTr();
                    return allTr.stream().filter(tr -> {
                        final List<WebElement> tds = tr.findElements(By.tagName("td"));
                        if (tds.isEmpty() || tds.size()<4) {
                            return false;
                        }
                        return true;
                    }).map(TestMsgTr::new).collect(Collectors.toList());
                }

                /**
                 * 点击所有的发送消息
                 *
                 * @return
                 */
                public TestOperate sendAll() {
                    findAllTestMsgTr().forEach(testMsgTr -> {
                        final WebElement send = testMsgTr.getSend();
                        testMsgTr.scrollToSelf();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        doClick(send);

                        acceptAlert();
                    });
                    return this;
                }

                /**
                 * 点击刷新测试结果
                 *
                 * @return
                 */
                @SneakyThrows
                public TestOperate refreshTestResult() {
                    final WebElement refresh = findElementByXPath("/html/body/div[3]/section/div/div[3]/div[1]/div[2]/button");
                    doClick(refresh);
                    Thread.sleep(1000);
                    return this;
                }

                /**
                 * 点击我要上线
                 *
                 * @return
                 */
                @SneakyThrows
                public TestOperate iWantToOnline() {
                    final WebElement refresh = findElementByXPath("/html/body/div[3]/section/div/div[3]/div[3]/button[2]");
                    scrollTo(refresh.getLocation());
                    doClick(refresh);
                    Thread.sleep(200);
                    return this;
                }

                /**
                 * 点击确认提醒
                 *
                 * @return
                 */
                @SneakyThrows
                public TestOperate accept() {

                    final WebElement refresh = findElementByXPath("/html/body/div[3]/section/div/div[11]/div[1]/div/div/div[2]/form/div/div/button[1]");
                    doClick(refresh);
                    Thread.sleep(1000);
                    return this;
                }

                /**
                 * 点击最后的确认提醒
                 *
                 * @return
                 */
                @SneakyThrows
                public TestOperate lastAccept() {

                    final WebElement refresh = findElementByXPath("/html/body/div[3]/section/div/div[11]/div[3]/div/div/div[2]/form/div/div/button[1]");
                    doClick(refresh);
                    Thread.sleep(1000);
                    return this;
                }


                /**
                 * 返回到企业列表
                 *
                 * @return AuthedAppOperate
                 */
                public AuthedAppOperate goBackEnterpriseListPage() {
                    final String backButtonXpath = "/html/body/div[3]/div/ul/li[8]/a";
                    final WebElement back = findElementByXPath(backButtonXpath);
                    doClick(back);
                    AuthedAppOperate authedAppOperate = new AuthedAppOperate();
                    return authedAppOperate;
                }


            }

            @SneakyThrows
            public TestOperate toTest(Set<Msg> msgs) {
                final WebElement openTest = findElementByXPath("/html/body/div[3]/section/div/div[2]/div[4]/button");
                doClick(openTest);
                //点击确认
                acceptAlert();
                //等待页面跳转
                findElementByXPath("/html/body/div[3]/section/div/div[3]/div[1]/div[2]/button");
                return new TestOperate(msgs);
            }

            /**
             * 点击接口配置及测试
             *
             * @return
             */
            public InterfaceConfigAndTestOperate clickConfigUrl() {
                //点击配置及测试
                final String configButtonXpath = "/html/body/div[3]/div/ul/li[4]/a";
                final WebElement config = findElementByXPath(configButtonXpath, 20);
                doClick(config);
                return this;
            }


            /**
             * 返回到企业列表
             *
             * @return AuthedAppOperate
             */
            public AuthedAppOperate goBackEnterpriseListPage() {
                final String backButtonXpath = "/html/body/div[3]/div/ul/li[8]/a";
                final WebElement back = findElementByXPath(backButtonXpath);
                doClick(back);
                AuthedAppOperate authedAppOperate = new AuthedAppOperate();
                return authedAppOperate;
            }

            /**
             * 获取配置列表中所有的div
             *
             * @return
             */
            private Map<Scheme, WebElement[]> sortAllScheme() {
                final List<WebElement> divs = getAllDiv();
                return sortAllScheme(divs);
            }

            /**
             * 从接口配置页面获取所有方案的div
             *
             * @return
             */
            private List<WebElement> getAllDiv() {
                //获取接口列表div
                final WebElement interfaceContent = findElementById("interface_content");
                return interfaceContent.findElements(By.tagName("div"));
            }

            /**
             * 从接口配置页面获取所有的tr
             *
             * @return
             */
            @SneakyThrows
            private List<WebElement> getAllTr() {
                try {
                    Thread.sleep(300);
                    //获取接口列表div
                    final WebElement interfaceContent = findElementById("interface_content");
                    return interfaceContent.findElements(By.tagName("tr"));
                } catch (Exception e) {
                    Thread.sleep(1000);
                    return getAllTr();
                }
            }

            /**
             * 从接口配置页面获取所有的消息订阅tr
             *
             * @param activeAllInterface
             * @return
             */
            private List<SelfElement> getTrs(final boolean activeAllInterface) {
//                final Map<String, Msg> map = Msg.map();
                final List<WebElement> allTr = getAllTr();
                return allTr.parallelStream()
                        .filter(tr -> {
                            final List<WebElement> tds = tr.findElements(By.tagName("td"));
                            if (tds.isEmpty() || tds.size() < 5) {
                                return false;
                            } else {

                                return true;
                            }
//                            final WebElement name = tds.get(1);
//                            final String text = name.getText();
//                            final Msg msg = map.get(text);
//                            return msg != null;
                        })
                        .filter(tr -> {
                            if (activeAllInterface) {
                                return true;
                            } else {
                                final List<WebElement> tds = tr.findElements(By.tagName("td"));
                                final WebElement ops = tds.get(5);
                                final List<WebElement> spans = ops.findElements(By.tagName("span"));
                                return spans.size() > 3;
                            }
                        })
                        //区分msgTr和interfaceTr
                        .map(tr -> {
                            final List<WebElement> tds = tr.findElements(By.tagName("td"));
                            final WebElement ops = tds.get(5);
                            final List<WebElement> spans = ops.findElements(By.tagName("span"));
                            if (spans.size() == 3) {
                                return new InterfaceTr(tr);
                            } else {
                                return new MsgTr(tr);
                            }

                        })
                        .collect(Collectors.toList());
            }


            /**
             * 在div 中查找消息订阅的trs(行集合)的stream
             *
             * @param webElement
             * @return
             */
            public Stream<InterfaceTr> getInterfaceTrStream(WebElement webElement) {
                final WebElement fanganInterfaceMessage = webElement.findElement(By.id("fangan_interface"));
                final List<WebElement> trs = fanganInterfaceMessage.findElements(By.tagName("tr"));
                return trs.stream().map(InterfaceTr::new);
            }

            /**
             * 在div 中查找消息订阅的trs(行集合)的stream
             *
             * @param webElement
             * @return
             */
            public Stream<MsgTr> getMsgTrStream(WebElement webElement) {
                final WebElement fanganInterfaceMessage = webElement.findElement(By.id("fangan_interface_message"));
                final List<WebElement> trs = fanganInterfaceMessage.findElements(By.tagName("tr"));
                return trs.stream().map(MsgTr::new);
            }

            /**
             * 在页面中查找出企业对结果哪些方案
             *
             * @param divs
             * @return
             */
            private Map<Scheme, WebElement[]> sortAllScheme(List<WebElement> divs) {
                Map<Scheme, WebElement[]> map = new HashMap<>();
                for (int i = 0; i < divs.size(); i++) {
                    final WebElement webElement = divs.get(i);
                    try {
                        final WebElement h2 = webElement.findElement(By.tagName("h2"));
                        final String text = h2.getText();
                        final Scheme scheme = findByKeyword(text);
                        WebElement[] webElementGroup = new WebElement[2];
                        webElementGroup[0] = webElement;
                        if (easy.msg()) {
                            webElementGroup[1] = divs.get(i + 1);
                        }
                        map.put(scheme, webElementGroup);
                    } catch (Exception e) {
                        continue;
                    }
                }
                return map;
            }

            /**
             * 指定方案类型订阅和配置服务地址
             *
             * @param scheme
             * @param testUrl
             * @param prodUrl
             * @return
             */
            public InterfaceConfigAndTestOperate replaceConfigUrl(Scheme scheme, final String testUrl, final String prodUrl) {
                final Map<Scheme, WebElement[]> schemeListMap = sortAllScheme();
                final WebElement[] webElements = schemeListMap.get(scheme);
                if (webElements == null) {
                    return this;
                }
                final WebElement apis = webElements[0];
                final WebElement msgs = webElements[1];
                if (msgs == null) {
                    return this;
                }


                //循环msgs
                getMsgTrStream(msgs).forEach(msgTr -> {
                    msgTr.scrollToSelf();
                    //替换配置地址
                    final WebElement configUrlEle = msgTr.getConfigUrl();
                    replaceConfigUrl(configUrlEle, testUrl, prodUrl);
                    //勾选复选框
                    msgTr.checked();
                });
                return this;
            }


            /**
             * 订阅消息并设置配置地址
             *
             * @param msgTr
             * @param test
             * @param prod
             */
            public void subscribeMsgAndSetConfigUrl(MsgTr msgTr, String test, String prod) {
                msgTr.activate();
                replaceConfigUrl(msgTr.getConfigUrl(), test, prod);
            }


            /**
             * 指定消息订阅和配置服务地址
             *
             * @param autoParam
             * @return
             */
            @SneakyThrows
            public InterfaceConfigAndTestOperate subscribeAndReplaceConfigUrl(final SafeAutoParam autoParam) {
                final Set<Msg> msgs = autoParam.getMsgs();
                final String testUrl = autoParam.getTestUrl();
                final String prodUrl = autoParam.getProdUrl();
                final String goodsTestUrl = autoParam.getGoodsTestUrl();
                final String goodsProdUrl = autoParam.getGoodsProdUrl();
                final boolean activeAllInterface = autoParam.isActiveAllInterface();
//                final List<MsgTr> msgTrs = getAllMsgTr(msgs);

                final List<SelfElement> trs = getTrs(activeAllInterface);
                //循环msgs
                trs.stream()
                        .peek(tr -> {
                            tr.scrollToSelf();
                            if (tr instanceof MsgTr) {
                                final MsgTr msgTr = (MsgTr) tr;
                                final Msg msg = msgTr.getMsg();
                                if (!msgs.contains(msg)) {
                                    //取消勾选无关的msg
                                    msgTr.unchecked();
                                }
                            }

                        })
                        //过滤掉无关的msg
                        .filter(tr -> {
                            if (tr instanceof MsgTr) {
                                final MsgTr msgTr = (MsgTr) tr;
                                return msgs.contains(msgTr.getMsg());
                            } else {
                                return true;
                            }
                        })
                        .forEach(tr -> {
                            tr.scrollToSelf();
                            //先确定订阅消息
                            tr.activate();
                            //替换配置地址
                            if (tr instanceof MsgTr) {
                                final MsgTr msgTr = (MsgTr) tr;
                                final WebElement configUrlEle = msgTr.getConfigUrl();
                                final Msg msg = msgTr.getMsg();
                                final boolean goodsMsg = msg.schemes().contains(Scheme.goods);
                                if (goodsMsg){
                                    replaceConfigUrl(configUrlEle, goodsTestUrl, goodsProdUrl);
                                }else{
                                    replaceConfigUrl(configUrlEle, testUrl, prodUrl);
                                }

                            } else {
                                return;
                            }

                            //勾选复选框
                            tr.checked();
                            try {
                                Thread.sleep(200);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        });
                Thread.sleep(2000);
                return this;
            }


            /**
             * 替换配置地址
             *
             * @param configUrlEle
             * @param testUrl
             * @param prodUrl
             */
            @SneakyThrows
            private InterfaceConfigAndTestOperate replaceConfigUrl(WebElement configUrlEle, String testUrl, String prodUrl) {
                doClick(configUrlEle);
                //等待之前的表单重新渲染
                Thread.sleep(300);
                final WebElement testUrlEle = findElementById("test_url");
                final String oldTestUrl = testUrlEle.getAttribute("value");
//                if (!testUrl.equals(oldTestUrl)) {
//                    doClear(testUrlEle);
                doSendKeysByJS(testUrlEle, testUrl);
//                }

                final WebElement formalUrlEle = findElementById("formal_url");
                final String oldFormalUrl = formalUrlEle.getAttribute("value");
//                if (!prodUrl.equals(oldFormalUrl)) {
//                    doClear(formalUrlEle);
                doSendKeysByJS(formalUrlEle, prodUrl);
//                }

                final WebElement saveButton = findElementByXPath("/html/body/div[3]/section/div/div[9]/div/div/div/div[2]/form/div[4]/div/button");
                doClick(saveButton);
                return this;

            }

            /**
             * 在页面中找出所有消息订阅的行
             *
             * @param divs
             * @return
             */
            public List<MsgTr> filterMsgTr(List<MsgTr> divs, List<Msg> msgs) {
                //先将msgs转换成map,在循环divs,时间复杂度就可以变成2N=>N
                final Map<String, Msg> msgMap = msgs.stream().collect(Collectors.toMap(
                        Msg::getTitle,
                        Function.identity()
                ));
                final List<MsgTr> collect = divs.stream().filter(
                        msgTr -> {
                            final String interfaceNameStr = msgTr.getInterfaceNameStr();
                            final Msg msg = msgMap.get(interfaceNameStr);
                            return msg != null;
                        }
                ).collect(Collectors.toList());
                return collect;

            }


            /**
             * 在页面中找出所有消息订阅的行
             *
             * @param divs
             * @return
             */
            public List<MsgTr> sortAllMsg(List<WebElement> divs) {
                final List<MsgTr> reduce = divs.stream()
                        .filter(div -> {
                            try {
                                final WebElement msgDiv = div.findElement(By.id("fangan_interface_message"));
                                if (msgDiv == null) {
                                    return false;
                                }
                                return true;
                            } catch (Exception e) {
                                return false;
                            }
                        }).map(div -> {
                            final List<WebElement> msgTrs = div.findElements(By.tagName("tr"));
                            return msgTrs.stream().map(MsgTr::new).collect(Collectors.toList());
                        }).reduce(new ArrayList<>(), (a, b) -> {
                            a.addAll(b);
                            return a;
                        });
                return reduce;

            }

            /**
             * 方案的div集合
             *
             * @param webElements
             * @return
             */
            public WebElement findOrderDiv(List<WebElement> webElements) {
                for (WebElement webElement : webElements) {
                    try {
                        final WebElement h2 = webElement.findElement(By.tagName("h2"));
                        final String text = h2.getText();
                        if (text.contains("订单")) {
                            return webElement;
                        }
                    } catch (Exception e) {
                        continue;
                    }
                }
                throw new IllegalArgumentException("webElements 中不存在订单方案的div");
            }


            /**
             * 勾选所有的复选框
             *
             * @param webElement
             */
            public void checkedAll(WebElement webElement) {
                final List<WebElement> msgTrs = getMsgTrs(webElement);
                for (WebElement msgTr : msgTrs) {
                    MsgTr msg = new MsgTr(msgTr);
                    final WebElement checkBoxElement = msg.getCheckBox();
                    if (checkBoxElement == null) {
                        continue;
                    }
                    msg.checked();
                    final WebElement checkBoxMarkElement = getCheckBoxMarkElement(msgTr);
                    if (checkBoxMarkElement != null) {
                        msg.unchecked();
                    }
                }
            }

            /**
             * 在div 中查找消息订阅的trs(行集合)
             *
             * @param webElement
             * @return
             */
            public List<WebElement> getMsgTrs(WebElement webElement) {
                final WebElement fanganInterfaceMessage = webElement.findElement(By.id("fangan_interface_message"));
                final List<WebElement> trs = fanganInterfaceMessage.findElements(By.tagName("tr"));
                return trs;
            }

            /**
             * 在div 中查找接口类型的trs(行集合)
             *
             * @param webElement
             * @return
             */
            public List<WebElement> getInterfaceTrs(WebElement webElement) {
                final WebElement fanganInterface = webElement.findElement(By.id("fangan_interface"));
                final List<WebElement> trs = fanganInterface.findElements(By.tagName("tr"));
                return trs;
            }

            /**
             * 获取一行中的复选框
             *
             * @param tr
             * @return
             */
            public WebElement getCheckBoxElement(WebElement tr) {
                final WebElement td = tr.findElements(By.tagName("td")).get(0);
                try {
                    return td.findElement(By.tagName("input"));
                } catch (Exception e) {
                    return null;
                }
            }

            /**
             * 获取一行中的复选框下的感叹号
             *
             * @param tr
             * @return
             */
            public WebElement getCheckBoxMarkElement(WebElement tr) {
                final WebElement td = tr.findElements(By.tagName("td")).get(0);
                try {
                    return td.findElement(By.tagName("span"));
                } catch (Exception e) {
                    return null;
                }
            }


        }


        /**
         * 点击某个企业的方案接口信息
         *
         * @param enterprise
         * @return
         */
        public InterfaceConfigAndTestOperate clickScheme(Ent enterprise) {
            final WebElement tbodyEle = findElementByXPath("/html/body/div[3]/div/div[2]/form/table/tbody");
            final List<WebElement> trElements = tbodyEle.findElements(By.tagName("tr"));
            // 去掉第一行的表头,获取所有的app 行
            final EnterpriseTr enterpriseTr = trElements.stream()
                    .skip(1)
                    .map(EnterpriseTr::new)
                    .filter(tr -> enterprise.getVendorId().equals(tr.getVenderIdStr()))
                    .findFirst()
                    .orElseThrow(IllegalArgumentException::new);

            enterpriseTr.scrollToSelf();
            final WebElement scheme = enterpriseTr.getScheme();
            doClick(scheme);

            return new InterfaceConfigAndTestOperate();

        }

    }

    /**
     * 确认弹出框
     */
    @SneakyThrows
    private static void acceptAlert() {
//        Thread.sleep(200);
//        try {
//            ChromeDriver.getInstance().switchTo().alert().accept();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        Thread.sleep(200);
    }


    /**
     * 等待输入验证码,并自动登陆到管理中心页面
     *
     * @param loginEle
     * @param validateCodeEle
     * @return
     */
    public AutoOperate waitInputAndLogin(WebElement loginEle, WebElement validateCodeEle) {
        WebElement logout = null;
        do {
            waitManualInput(validateCodeEle);
            //点击登陆
            doClick(loginEle);
            login = true;

            try {

                logout = findElementByXPath("/html/body/div[1]/div/div/div[3]/div/a");
            } catch (Exception e) {
                validateCodeEle.clear();
                logout = null;
            }
        } while (logout == null);
        return this;
    }


    /**
     * 操作滚动条
     *
     * @param x
     * @param y
     */
    public static void scrollTo(int x, int y) {
        String js = "window.scrollTo(arguments[0],arguments[1])";
        ChromeDriver.getInstance().executeScript(js, x, y);
    }

    /**
     * 操作滚动条
     *
     * @param point
     */
    public static void scrollTo(Point point) {
        String js = "window.scrollTo(arguments[0],arguments[1])";
        scrollTo(point.getX(), point.getY() - 50);
    }


    public static void waitManualInput(WebElement webElement) {
        String text = null;
        do {
            text = webElement.getAttribute("value");
        } while (StringUtils.isBlank(text) || text.length() != 4);

    }

    @SneakyThrows
    public static WebElement findElementByXPath(String xpath) {
        WebDriverWait wait = new WebDriverWait(ChromeDriver.getInstance(), 5);
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
    }

    @SneakyThrows
    public static WebElement findElementByXPath(String xpath, int timeOutInSeconds) {
        WebDriverWait wait = new WebDriverWait(ChromeDriver.getInstance(), timeOutInSeconds);
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
    }

    @SneakyThrows
    public static WebElement findElementById(String id) {
        WebDriverWait wait = new WebDriverWait(ChromeDriver.getInstance(), 5);
        return wait.until(ExpectedConditions.presenceOfElementLocated(By.id(id)));

    }


    @SneakyThrows
    public static void doClick(WebElement webElement) {
//        Thread.sleep(100);
//        webElement.click();
//        Thread.sleep(100);
        try {
            Thread.sleep(100);
            String js = "arguments[0].click()";
            ChromeDriver.getInstance().executeScript(js, webElement);
            Thread.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
            doClick(webElement);
        }
    }

    @SneakyThrows
    public static void doClickByJS(WebElement webElement) {
        Thread.sleep(100);
        String js = "arguments[0].click()";
        ChromeDriver.getInstance().executeScript(js, webElement);
        Thread.sleep(100);
    }

    @SneakyThrows
    public static void doSendKeysByJS(WebElement webElement, String keys) {
        Thread.sleep(100);
        String js = "arguments[0].value='" + keys + "'";
        ChromeDriver.getInstance().executeScript(js, webElement);
        Thread.sleep(100);
    }

    @SneakyThrows
    public static void doSendKeys(WebElement webElement, String keys) {
        try {
            Thread.sleep(100);
//        webElement.sendKeys(keys);

            String js = "arguments[0].value='" + keys + "'";
            ChromeDriver.getInstance().executeScript(js, webElement);
            Thread.sleep(100);
        } catch (Exception e) {
            doSendKeys(webElement, keys);
        }
    }

    @SneakyThrows
    public static void doClear(WebElement webElement) {
        Thread.sleep(100);
        webElement.clear();
        Thread.sleep(100);
    }

    @SneakyThrows
    public static String getText(WebElement webElement) {
        Thread.sleep(100);
        final String text = webElement.getText();
        if (StringUtils.isBlank(text)) {
            return getText(webElement);
        }
        return text;
    }
}
